#include "uln.h"
#include "stm8s_gpio.h"
#include "stm8s_clk.h"

/**
 * @brief IO pin structure definition
 *        Contains port, pin number and description
 */
typedef struct
{
    GPIO_TypeDef *port;      // GPIO port
    GPIO_Pin_TypeDef pin;    // GPIO pin number
    const char *description; // Pin description
} io_pin_t;

/**
 * @brief ULN2003 channel configuration array
 *        Maps channel index to actual hardware pins
 *        Corresponding to schematic diagram connections
 */
static const io_pin_t uln_channels[ULN_CH_MAX] = {
    // ---------------- U13 (ULN1) ----------------
    {GPIOF, GPIO_PIN_7, "ULN1_16 (PF7)"}, // ULN1_16 → U13 的 16 脚
    {GPIOH, GPIO_PIN_3, "ULN1_15 (PH3)"}, // ULN1_15 → U13 的 15 脚
    {GPIOH, GPIO_PIN_2, "ULN1_14 (PH2)"}, // ULN1_14 → U13 的 14 脚
    {GPIOH, GPIO_PIN_1, "ULN1_13 (PH1)"}, // ULN1_13 → U13 的 13 脚
    {GPIOH, GPIO_PIN_0, "ULN1_12 (PH0)"}, // ULN1_12 → U13 的 12 脚
    {GPIOA, GPIO_PIN_6, "ULN1_11 (PA6)"}, // ULN1_11 → U13 的 11 脚
    {GPIOA, GPIO_PIN_3, "ULN1_10 (PA3)"}, // ULN1_10 → U13 的 10 脚
                                          // ---------------- U24 (ULN2) ----------------
    {GPIOB, GPIO_PIN_6, "ULN2_16 (PB6)"}, // ULN2_16 → U24 的 16 脚
    {GPIOB, GPIO_PIN_7, "ULN2_15 (PB7)"}, // ULN2_15 → U24 的 15 脚
    {GPIOF, GPIO_PIN_0, "ULN2_14 (PF0)"}, // ULN2_14 → U24 的 14 脚
    {GPIOF, GPIO_PIN_3, "ULN2_13 (PF3)"}, // ULN2_13 → U24 的 13 脚
    {GPIOF, GPIO_PIN_4, "ULN2_12 (PF4)"}, // ULN2_12 → U24 的 12 脚
    {GPIOF, GPIO_PIN_5, "ULN2_11 (PF5)"}, // ULN2_11 → U24 的 11 脚
    {GPIOF, GPIO_PIN_6, "ULN2_10 (PF6)"}, // ULN2_10 → U24 的 10 脚
    // ---------------- U32 (ULN3) ----------------
    {GPIOE, GPIO_PIN_5, "ULN3_16 (PE5)"}, // ULN3_16 → U32 的 16 脚
    {GPIOE, GPIO_PIN_6, "ULN3_15 (PE6)"}, // ULN3_15 → U32 的 15 脚
    {GPIOE, GPIO_PIN_7, "ULN3_14 (PE7)"}, // ULN3_14 → U32 的 14 脚
    {GPIOH, GPIO_PIN_7, "ULN3_13 (PH7)"}, // ULN3_13 → U32 的 13 脚
    {GPIOH, GPIO_PIN_6, "ULN3_12 (PH6)"}, // ULN3_12 → U32 的 12 脚（若有）
    {GPIOH, GPIO_PIN_5, "ULN3_11 (PH5)"}, // ULN3_11 → U32 的 11 脚（若有）
    {GPIOH, GPIO_PIN_4, "ULN3_10 (PH4)"}, // ULN3_10 → U32 的 10 脚（若有）
    // ---------------- U27 (ULN4) ----------------
    {GPIOC, GPIO_PIN_0, "ULN4_16 (PC0)"}, // ULN4_16 → U27 的 16 脚
    {GPIOG, GPIO_PIN_3, "ULN4_15 (PG3)"}, // ULN4_15 → U27 的 15 脚
    {GPIOG, GPIO_PIN_2, "ULN4_14 (PG2)"}, // ULN4_14 → U27 的 14 脚
    {GPIOG, GPIO_PIN_1, "ULN4_13 (PG1)"}, // ULN4_13 → U27 的 13 脚
    {GPIOG, GPIO_PIN_0, "ULN4_12 (PG0)"}, // ULN4_12 → U27 的 12 脚（若有）
    {GPIOC, GPIO_PIN_7, "ULN4_11 (PC7)"}, // ULN4_11 → U27 的 11 脚（若有）
    {GPIOC, GPIO_PIN_6, "ULN4_10 (PC6)"}, // ULN4_10 → U27 的 10 脚（若有）
    // ---------------- U20 (ULN5) ----------------
    {GPIOI, GPIO_PIN_4, "ULN5_16 (PI4)"}, // ULN5_16 → U20 的 16 脚（替换为真实端口！）
    {GPIOI, GPIO_PIN_3, "ULN5_15 (PI3)"}, // ULN5_15 → U20 的 15 脚
    {GPIOI, GPIO_PIN_2, "ULN5_14 (PI2)"}, // ULN5_14 → U20 的 14 脚
    {GPIOI, GPIO_PIN_1, "ULN5_13 (PI1)"}, // ULN5_13 → U20 的 13 脚
    {GPIOI, GPIO_PIN_0, "ULN5_12 (PI0)"}, // ULN5_12 → U20 的 12 脚（若有）
    {GPIOG, GPIO_PIN_4, "ULN5_11 (PG5)"}, // ULN5_11 → U20 的 11 脚（若有）
    {GPIOC, GPIO_PIN_5, "ULN5_10 (PG6)"}, // ULN5_10 → U20 的 10 脚（若有）
    // ---------------- U18 (ULN6) ----------------
    {GPIOC, GPIO_PIN_4, "ULN6_16 (PC4)"}, // ULN6_16 → U18 的 16 脚
    {GPIOC, GPIO_PIN_3, "ULN6_15 (PC3)"}, // ULN6_15 → U18 的 15 脚
    {GPIOC, GPIO_PIN_2, "ULN6_14 (PC2)"}, // ULN6_14 → U18 的 14 脚
    {GPIOC, GPIO_PIN_1, "ULN6_13 (PC1)"}, // ULN6_13 → U18 的 13 脚

};

/**
 * @brief Initialize all ULN2003 control pins as output
 * @param None
 * @return None
 */
static void uln_init_pins(void)
{
    for (uint8_t i = 0; i < ULN_CH_MAX; i++)
    {
        GPIO_Init(uln_channels[i].port,
                  uln_channels[i].pin,
                  GPIO_MODE_OUT_PP_LOW_FAST);
    }
}

/**
 * @brief Initialize ULN2003 driver and associated hardware
 * @param None
 * @return None
 */
void uln_init(void)
{
    uln_init_pins();
}

/**
 * @brief Set state of a specific ULN2003 channel
 * @param channel: ULN channel index (ULN_CH_U01 to ULN_CH_U23)
 * @param state: 1 for high level, 0 for low level
 * @return 1 if successful, 0 if invalid channel
 */
uint8_t uln_set_channel(int channel, uint8_t state)
{
    if (channel >= ULN_CH_MAX)
    {
        return 0; // Invalid channel
    }

    if (state)
    {
        GPIO_WriteHigh(uln_channels[channel].port,
                       uln_channels[channel].pin);
    }
    else
    {
        GPIO_WriteLow(uln_channels[channel].port,
                      uln_channels[channel].pin);
    }

    return 1; // Success
}

/**
 * @brief Get current state of a specific ULN2003 channel
 * @param channel: ULN channel index (ULN_CH_U01 to ULN_CH_U23)
 * @return 1 if high, 0 if low, 0xFF if invalid channel
 */
uint8_t uln_get_channel(uln_channel_t channel)
{
    if (channel >= ULN_CH_MAX)
    {
        return 0xFF; // Invalid channel
    }

    return ((GPIO_ReadOutputData(uln_channels[channel].port) & uln_channels[channel].pin)? 1: 0);
}

// 验证通道有效性
static int is_valid_channel(int ch)
{
    return (ch >= 0 && ch < ULN_CH_MAX);
}

// 所有通道设置为指定状态
static void set_all_channels(uint8_t state)
{
    if (state != 0 && state != 1)
    {
        printf("状态错误！只能设置0或1\n");
        return;
    }

    printf("所有通道设置为%d...\n", state);
    for (int i = 0; i < ULN_CH_MAX; i++)
    {
        uln_set_channel(i, state);
    }
}

// 指定通道设置为指定状态
static void set_one_channel(int ch, uint8_t state)
{
    if (!is_valid_channel(ch))
    {
        printf("通道错误！有效范围0-%d\n", ULN_CH_MAX - 1);
        return;
    }
    if (state != 0 && state != 1)
    {
        printf("状态错误！只能设置0或1\n");
        return;
    }

    printf("通道%d设置为%d\n", ch, state);
    uln_set_channel(ch, state);
}

// MSH命令入口
 void uln_ctrl(int argc, char **argv)
{
    if (argc == 2)
    {
        // 所有通道设置：uln_ctrl all <0/1>
        if (strcmp(argv[1], "all") == 0)
        {
            printf("用法: uln_ctrl all <0/1>\n");
            return;
        }else if (strcmp(argv[1], "show") == 0)
        {
            for (int i = 0; i < ULN_CH_MAX; i++)
            {
                // 现实通道信息
                printf("通道%d: %s %s\n", i, uln_channels[i].description, uln_get_channel(i) ? "ON" : "OFF");
            }
        }
    }
    else if (argc == 3)
    {
        // 所有通道统一设置
        if (strcmp(argv[1], "all") == 0)
        {
            set_all_channels(atoi(argv[2]));
            return;
        }
        
        // 指定通道设置
        else
        {
            set_one_channel(atoi(argv[1]), atoi(argv[2]));
            return;
        }
    }

    // 命令提示
    printf("用法:\n");
    printf("  所有通道设置: uln_ctrl all <0/1>\n");
    printf("  指定通道设置: uln_ctrl <通道号 %d - %d> <0/1>\n",ULN1_16,ULN6_13);
    printf("示例:\n");
    printf("  uln_ctrl all 0   # 所有通道输出0\n");
    printf("  uln_ctrl 3 1     # 通道3输出1\n");
    printf("  uln_ctrl show\n");
}


